﻿using System;
using System.Windows;
using System.Xml.Linq;

using Hetymine.Executioner.Data;

using Perseus.Windows;
using Perseus.Xml;

namespace Hetymine.Executioner.Plugins.General.Notes {
    public class Note : IData {
        private bool _IsVisible;
        private Display _Display;

        public Note() : this(string.Empty, string.Empty) { }
        public Note(string name, string data) {
            this.Name = name;
            this.Data = data;

            this.Time = 0;            

            this.Left = 0;
            this.Top = 0;
            this.Width = 0;
            this.Height = 0;

            this.ShowInTaskbar = Executioner.Config.GetBool("Notes.Static", "Show In Taskbar", false);
            this.Topmost = Executioner.Config.GetBool("Notes.Static", "Topmost", false);
        }

        public event EventHandler NoteClosed;

        public string Name { get; set; }
        public string Data { get; set; }
        public int Time { get; set; }
        private bool ShowInTaskbar { get; set; }
        private bool Topmost { get; set; }
        public bool IsVisible {
            get { return this._IsVisible; }
            set {
                if (value) {
                    if (this._Display == null) {
                        this._Display = new Display(this.Data, this.Time, false);
                        this._Display.Title = "Note: " + this.Name;
                        this._Display.Text = this.Data;
                        this._Display.ShowInTaskbar = this.ShowInTaskbar;
                        this._Display.Topmost = this.Topmost;
                        this._Display.cNote.TextChanged += new System.Windows.Controls.TextChangedEventHandler(Note_TextChanged);                        
                        this._Display.Closing += new System.ComponentModel.CancelEventHandler(Display_Closing);
                        this._Display.Closed += new EventHandler(Display_Closed);
                        this._Display.Show();

                        // If width or height is 0, then position in default spot
                        if (this.Width == 0 || this.Height == 0) {
                            int display = Executioner.Config.GetInt("Notes.Static", "Display", -1);
                            string alignment = Executioner.Config.GetString("Notes.Static", "Alignment", "centre centre");
                            double left = Executioner.Config.GetInt("Notes.Static", "Left", 0);
                            double top = Executioner.Config.GetInt("Notes.Static", "Top", 0);
                            
                            Point p = Perseus.Windows.Display.Position(display, alignment, left, top, this._Display.ActualWidth, this._Display.ActualHeight);
                            this._Display.Left = p.X;
                            this._Display.Top = p.Y;
                            this.UpdateNote();
                        }
                        else {
                            this._Display.Left = this.Left;
                            this._Display.Top = this.Top;
                            this._Display.Width = this.Width;
                            this._Display.Height = this.Height;
                        }
                    }

                    // Should the users desktop configuration change,
                    // ensure that that note is still on screen
                    this._Display.EnsureOnScreen();

                    this._Display.Activate();
                    this._Display.cNote.Focus();                    
                }
                else if (this._Display != null) {
                    this._Display.Close();                    
                }

                this._IsVisible = value;
            }
        }

        #region Events
        private void Note_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) {
            this.Data = this._Display.cNote.Text;
        }
        private void Display_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
            this.UpdateNote();
        }
        private void Display_Closed(object sender, EventArgs e) {
            this._Display = null;
            this._IsVisible = false;

            if (this.NoteClosed != null) {
                this.NoteClosed(this, EventArgs.Empty);
            }
        }
        #endregion

        public double Left { get; set; }
        public double Top { get; set; }
        public double Width { get; set; }
        public double Height { get; set; }

        private void UpdateNote() {
            if (this._Display != null) {
                this.Left = this._Display.Left;
                this.Top = this._Display.Top;
                this.Width = this._Display.Width;
                this.Height = this._Display.Height;
                this.ShowInTaskbar = this._Display.ShowInTaskbar;
                this.Topmost = this._Display.Topmost;
            }
        }

        #region IData
        public void Load(XElement element) {
            this.ShowInTaskbar = element.Attribute("ShowInTaskbar").BoolOrFalse();
            this.Topmost = element.Attribute("Topmost").BoolOrFalse();

            this.Name = element.Element("Name").ValueOrEmpty();
            this.Data = element.Element("Data").ValueOrEmpty();

            var position = element.Element("Position");

            if (position != null) {
                this.Left = position.Attribute("Left").DoubleOrZero();
                this.Top = position.Attribute("Top").DoubleOrZero();
                this.Width = position.Attribute("Width").DoubleOr(double.NaN);
                this.Height = position.Attribute("Height").DoubleOr(double.NaN);
            }

            this.Time = element.Attribute("Time").IntOrZero();

            this.IsVisible = element.Attribute("Visible").BoolOrFalse();
        }
        public XElement Save() {
            this.UpdateNote();

            XElement xe = new XElement("Note");

            xe.Add(new XAttribute("ShowInTaskbar", this.ShowInTaskbar));
            xe.Add(new XAttribute("Topmost", this.Topmost));

            xe.Add(new XElement("Name", this.Name));
            xe.Add(new XElement("Data", this.Data));

            if (this.Width != 0) {
                var position = new XElement("Position");                
                position.Add(new XAttribute("Left", this.Left));
                position.Add(new XAttribute("Top", this.Top));
                if (!double.IsNaN(this.Width)) {
                    position.Add(new XAttribute("Width", this.Width));
                }
                if (!double.IsNaN(this.Height)) {
                    position.Add(new XAttribute("Height", this.Height));
                }
                xe.Add(position);
            }

            if (this.Time == 0 && this.IsVisible) {
                xe.Add(new XAttribute("Visible", true));
            }
            xe.Add(new XAttribute("Time", this.Time));

            return xe;
        }
        #endregion
    }
}
